//
//  KooCalendarModel.h
//  KooIEDUCalendarDemo
//
//  Created by nowcoder on 2024.
//

#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

/**
 * 日期单元格状态枚举
 */
typedef NS_ENUM(NSInteger, KooCalendarCellState) {
    KooCalendarCellStateNormal,     // 普通状态
    KooCalendarCellStateToday,      // 今日状态
    KooCalendarCellStateSelected,   // 选中状态
    KooCalendarCellStateDisabled,   // 禁用状态
    KooCalendarCellStateOtherMonth  // 其他月份的日期
};

/**
 * 日期单元格数据模型
 */
@interface KooCalendarCellModel : NSObject

/** 日期对象 */
@property (nonatomic, strong) NSDate *date;

/** 日期数字 */
@property (nonatomic, assign) NSInteger day;

/** 单元格状态 */
@property (nonatomic, assign) KooCalendarCellState state;

/** 是否是今日 */
@property (nonatomic, assign, readonly) BOOL isToday;

/** 是否已选中 */
@property (nonatomic, assign, readonly) BOOL isSelected;

/** 是否可选择 */
@property (nonatomic, assign, readonly) BOOL isSelectable;

/** 是否属于当前月份 */
@property (nonatomic, assign, readonly) BOOL isCurrentMonth;

/** 显示文本（可自定义） */
@property (nonatomic, copy, nullable) NSString *displayText;

/**
 * 初始化日期单元格模型
 * @param date 日期对象
 * @param currentMonthDate 当前显示月份的任意日期
 * @return 单元格模型实例
 */
- (instancetype)initWithDate:(NSDate *)date currentMonthDate:(NSDate *)currentMonthDate;

/**
 * 更新单元格状态
 * @param state 新状态
 */
- (void)updateState:(KooCalendarCellState)state;

@end

/**
 * 日历数据管理模型
 */
@interface KooCalendarModel : NSObject

/** 当前显示的月份日期 */
@property (nonatomic, strong) NSDate *currentMonthDate;

/** 当前月份的日期单元格数据数组 */
@property (nonatomic, strong, readonly) NSArray<KooCalendarCellModel *> *cellModels;

/** 选中的日期集合 */
@property (nonatomic, strong, readonly) NSMutableSet<NSDate *> *selectedDates;

/** 今日日期 */
@property (nonatomic, strong, readonly) NSDate *today;

/** 日历对象 */
@property (nonatomic, strong, readonly) NSCalendar *calendar;

/** 日期格式化器 */
@property (nonatomic, strong, readonly) NSDateFormatter *dateFormatter;

// MARK: - 初始化方法
/**
 * 初始化日历数据模型
 * @param currentDate 当前显示的月份日期
 */
- (instancetype)initWithCurrentDate:(NSDate *)currentDate;

// MARK: - 数据操作方法
/**
 * 切换到指定月份
 * @param date 目标月份的任意日期
 */
- (void)switchToMonth:(NSDate *)date;

/**
 * 选中指定日期
 * @param date 要选中的日期
 * @return YES表示选中成功，NO表示选中失败
 */
- (BOOL)selectDate:(NSDate *)date;

/**
 * 取消选中指定日期
 * @param date 要取消选中的日期
 */
- (void)deselectDate:(NSDate *)date;

/**
 * 清空所有选中的日期
 */
- (void)clearSelectedDates;

/**
 * 设置预选中的日期数组
 * @param dates 预选中的日期数组
 */
- (void)setPreSelectedDates:(NSArray<NSDate *> *)dates;

// MARK: - 查询方法
/**
 * 判断指定日期是否已选中
 * @param date 要查询的日期
 * @return YES表示已选中，NO表示未选中
 */
- (BOOL)isDateSelected:(NSDate *)date;

/**
 * 判断指定日期是否为今日
 * @param date 要查询的日期
 * @return YES表示是今日，NO表示不是今日
 */
- (BOOL)isToday:(NSDate *)date;

/**
 * 判断指定日期是否可选择
 * @param date 要查询的日期
 * @param onlyFutureDates 是否只允许选择未来日期
 * @return YES表示可选择，NO表示不可选择
 */
- (BOOL)isDateSelectable:(NSDate *)date onlyFutureDates:(BOOL)onlyFutureDates;

/**
 * 判断指定日期是否属于当前显示的月份
 * @param date 要查询的日期
 * @return YES表示属于当前月份，NO表示不属于
 */
- (BOOL)isDateInCurrentMonth:(NSDate *)date;

/**
 * 获取当前月份的第一天
 * @return 当前月份第一天的日期
 */
- (NSDate *)firstDayOfCurrentMonth;

/**
 * 获取当前月份的最后一天
 * @return 当前月份最后一天的日期
 */
- (NSDate *)lastDayOfCurrentMonth;

/**
 * 获取指定日期的下一个月的相同日期
 * @param date 基准日期
 * @return 下一个月的日期
 */
- (NSDate *)nextMonthFromDate:(NSDate *)date;

/**
 * 获取指定日期的上一个月的相同日期
 * @param date 基准日期
 * @return 上一个月的日期
 */
- (NSDate *)previousMonthFromDate:(NSDate *)date;

// MARK: - 格式化方法
/**
 * 格式化日期为显示字符串
 * @param date 要格式化的日期
 * @param format 格式字符串
 * @return 格式化后的字符串
 */
- (NSString *)formatDate:(NSDate *)date withFormat:(NSString *)format;

/**
 * 获取日期的天数
 * @param date 日期对象
 * @return 天数
 */
- (NSInteger)dayFromDate:(NSDate *)date;

/**
 * 比较两个日期是否是同一天
 * @param date1 日期1
 * @param date2 日期2
 * @return YES表示是同一天，NO表示不是
 */
- (BOOL)isSameDay:(NSDate *)date1 withDate:(NSDate *)date2;

@end

NS_ASSUME_NONNULL_END 